package com.merry.jcip;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * ConcurrentHashMap 在错误的使用下出现了线程安全问题的案例
 *
 */
@SuppressWarnings("all")
public class NotThreadSafeConcurrentHashMap {

    public static Map<Integer,Integer> map =new ConcurrentHashMap<Integer, Integer>();

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i=0;i<10;i++){
            executorService.execute(new Runnable() {
                public void run() {
                    Random random = new Random();
                    int randomNum = random.nextInt(10);
                    //方案一：虽然concurrent的containsKey和put方法都是线程安全的，但是在该代码中，还是会出现并发问题。这是由于containsKey和put组合的方法不是原子操作。
                    if(map.containsKey(randomNum)){
                        map.put(randomNum,map.get(randomNum)+1);
                    }else{
                        map.put(randomNum,1);
                    }

                    //方案二：修改一下，解决这个问题。 添加同步代码块解决线程安全问题。
                    countRandom(randomNum);
                }
            });
        }
        System.out.println(map);
    }

    //添加同步代码块让containsKey和put方法变成原子方法。
    private static synchronized void countRandom(int randomNum) {
        if(map.containsKey(randomNum)){
            map.put(randomNum,map.get(randomNum)+1);
        }else{
            map.put(randomNum,1);
        }
    }


}
